home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / asynchat.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-29  |  8.0 KB  |  257 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. """A class supporting chat-style (command/response) protocols.
  5.  
  6. This class adds support for 'chat' style protocols - where one side
  7. sends a 'command', and the other sends a response (examples would be
  8. the common internet protocols - smtp, nntp, ftp, etc..).
  9.  
  10. The handle_read() method looks at the input stream for the current
  11. 'terminator' (usually '\\r\\n' for single-line responses, '\\r\\n.\\r\\n'
  12. for multi-line output), calling self.found_terminator() on its
  13. receipt.
  14.  
  15. for example:
  16. Say you build an async nntp client using this class.  At the start
  17. of the connection, you'll have self.terminator set to '\\r\\n', in
  18. order to process the single-line greeting.  Just before issuing a
  19. 'LIST' command you'll set it to '\\r\\n.\\r\\n'.  The output of the LIST
  20. command will be accumulated (using your own 'collect_incoming_data'
  21. method) up to the terminator, and then control will be returned to
  22. you - by calling your self.found_terminator() method.
  23. """
  24. import socket
  25. import asyncore
  26. from collections import deque
  27.  
  28. class async_chat(asyncore.dispatcher):
  29.     '''This is an abstract class.  You must derive from this class, and add
  30.     the two methods collect_incoming_data() and found_terminator()'''
  31.     ac_in_buffer_size = 4096
  32.     ac_out_buffer_size = 4096
  33.     
  34.     def __init__(self, conn = None):
  35.         self.ac_in_buffer = ''
  36.         self.ac_out_buffer = ''
  37.         self.producer_fifo = fifo()
  38.         asyncore.dispatcher.__init__(self, conn)
  39.  
  40.     
  41.     def collect_incoming_data(self, data):
  42.         raise NotImplementedError, 'must be implemented in subclass'
  43.  
  44.     
  45.     def found_terminator(self):
  46.         raise NotImplementedError, 'must be implemented in subclass'
  47.  
  48.     
  49.     def set_terminator(self, term):
  50.         '''Set the input delimiter.  Can be a fixed string of any length, an integer, or None'''
  51.         self.terminator = term
  52.  
  53.     
  54.     def get_terminator(self):
  55.         return self.terminator
  56.  
  57.     
  58.     def handle_read(self):
  59.         
  60.         try:
  61.             data = self.recv(self.ac_in_buffer_size)
  62.         except socket.error:
  63.             why = None
  64.             self.handle_error()
  65.             return None
  66.  
  67.         self.ac_in_buffer = self.ac_in_buffer + data
  68.         while self.ac_in_buffer:
  69.             lb = len(self.ac_in_buffer)
  70.             terminator = self.get_terminator()
  71.             if not terminator:
  72.                 self.collect_incoming_data(self.ac_in_buffer)
  73.                 self.ac_in_buffer = ''
  74.                 continue
  75.             if isinstance(terminator, int) or isinstance(terminator, long):
  76.                 n = terminator
  77.                 if lb < n:
  78.                     self.collect_incoming_data(self.ac_in_buffer)
  79.                     self.ac_in_buffer = ''
  80.                     self.terminator = self.terminator - lb
  81.                 else:
  82.                     self.collect_incoming_data(self.ac_in_buffer[:n])
  83.                     self.ac_in_buffer = self.ac_in_buffer[n:]
  84.                     self.terminator = 0
  85.                     self.found_terminator()
  86.             lb < n
  87.             terminator_len = len(terminator)
  88.             index = self.ac_in_buffer.find(terminator)
  89.             if index != -1:
  90.                 if index > 0:
  91.                     self.collect_incoming_data(self.ac_in_buffer[:index])
  92.                 
  93.                 self.ac_in_buffer = self.ac_in_buffer[index + terminator_len:]
  94.                 self.found_terminator()
  95.                 continue
  96.             index = find_prefix_at_end(self.ac_in_buffer, terminator)
  97.             if index:
  98.                 if index != lb:
  99.                     self.collect_incoming_data(self.ac_in_buffer[:-index])
  100.                     self.ac_in_buffer = self.ac_in_buffer[-index:]
  101.                 
  102.                 break
  103.                 continue
  104.             self.collect_incoming_data(self.ac_in_buffer)
  105.             self.ac_in_buffer = ''
  106.  
  107.     
  108.     def handle_write(self):
  109.         self.initiate_send()
  110.  
  111.     
  112.     def handle_close(self):
  113.         self.close()
  114.  
  115.     
  116.     def push(self, data):
  117.         self.producer_fifo.push(simple_producer(data))
  118.         self.initiate_send()
  119.  
  120.     
  121.     def push_with_producer(self, producer):
  122.         self.producer_fifo.push(producer)
  123.         self.initiate_send()
  124.  
  125.     
  126.     def readable(self):
  127.         '''predicate for inclusion in the readable for select()'''
  128.         return len(self.ac_in_buffer) <= self.ac_in_buffer_size
  129.  
  130.     
  131.     def writable(self):
  132.         '''predicate for inclusion in the writable for select()'''
  133.         if self.ac_out_buffer == '' and self.producer_fifo.is_empty():
  134.             pass
  135.         return not (self.connected)
  136.  
  137.     
  138.     def close_when_done(self):
  139.         '''automatically close this channel once the outgoing queue is empty'''
  140.         self.producer_fifo.push(None)
  141.  
  142.     
  143.     def refill_buffer(self):
  144.         while len(self.producer_fifo):
  145.             p = self.producer_fifo.first()
  146.             if p is None:
  147.                 if not self.ac_out_buffer:
  148.                     self.producer_fifo.pop()
  149.                     self.close()
  150.                 
  151.                 return None
  152.             elif isinstance(p, str):
  153.                 self.producer_fifo.pop()
  154.                 self.ac_out_buffer = self.ac_out_buffer + p
  155.                 return None
  156.             
  157.             data = p.more()
  158.             if data:
  159.                 self.ac_out_buffer = self.ac_out_buffer + data
  160.                 return None
  161.             else:
  162.                 self.producer_fifo.pop()
  163.             data
  164.             return None
  165.             continue
  166.             return None
  167.  
  168.     
  169.     def initiate_send(self):
  170.         obs = self.ac_out_buffer_size
  171.         if len(self.ac_out_buffer) < obs:
  172.             self.refill_buffer()
  173.         
  174.         if self.ac_out_buffer and self.connected:
  175.             
  176.             try:
  177.                 num_sent = self.send(self.ac_out_buffer[:obs])
  178.                 if num_sent:
  179.                     self.ac_out_buffer = self.ac_out_buffer[num_sent:]
  180.             except socket.error:
  181.                 why = None
  182.                 self.handle_error()
  183.                 return None
  184.             except:
  185.                 None<EXCEPTION MATCH>socket.error
  186.             
  187.  
  188.         None<EXCEPTION MATCH>socket.error
  189.  
  190.     
  191.     def discard_buffers(self):
  192.         self.ac_in_buffer = ''
  193.         self.ac_out_buffer = ''
  194.         while self.producer_fifo:
  195.             self.producer_fifo.pop()
  196.  
  197.  
  198.  
  199. class simple_producer:
  200.     
  201.     def __init__(self, data, buffer_size = 512):
  202.         self.data = data
  203.         self.buffer_size = buffer_size
  204.  
  205.     
  206.     def more(self):
  207.         if len(self.data) > self.buffer_size:
  208.             result = self.data[:self.buffer_size]
  209.             self.data = self.data[self.buffer_size:]
  210.             return result
  211.         else:
  212.             result = self.data
  213.             self.data = ''
  214.             return result
  215.  
  216.  
  217.  
  218. class fifo:
  219.     
  220.     def __init__(self, list = None):
  221.         if not list:
  222.             self.list = deque()
  223.         else:
  224.             self.list = deque(list)
  225.  
  226.     
  227.     def __len__(self):
  228.         return len(self.list)
  229.  
  230.     
  231.     def is_empty(self):
  232.         return not (self.list)
  233.  
  234.     
  235.     def first(self):
  236.         return self.list[0]
  237.  
  238.     
  239.     def push(self, data):
  240.         self.list.append(data)
  241.  
  242.     
  243.     def pop(self):
  244.         if self.list:
  245.             return (1, self.list.popleft())
  246.         else:
  247.             return (0, None)
  248.  
  249.  
  250.  
  251. def find_prefix_at_end(haystack, needle):
  252.     l = len(needle) - 1
  253.     while l and not haystack.endswith(needle[:l]):
  254.         l -= 1
  255.     return l
  256.  
  257.